{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial 6 - Managing simulation outputs"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the previous tutorials we have interacted with the outputs of the simulation via the default plotting functionality. However, usually we need to access the output data to manipulate it or transfer to another software, which is the topic of this notebook.\n",
    "\n",
    "We start by building and solving our model as shown in previous notebooks:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.3.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.0\u001B[0m\n",
      "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "An NVIDIA GPU may be present on this machine, but a CUDA-enabled jaxlib is not installed. Falling back to cpu.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<pybamm.solvers.solution.Solution at 0x7f5e5b147fd0>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pip install \"pybamm[plot,cite]\" -q    # install PyBaMM if it is not installed\n",
    "import pybamm\n",
    "\n",
    "model = pybamm.lithium_ion.SPMe()\n",
    "sim = pybamm.Simulation(model)\n",
    "sim.solve([0, 3600])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Accessing solution variables"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now access the solved variables directly to visualise or create our own plots. We first extract the solution object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "solution = sim.solution"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the solution object is also returned when calling the `solve` method, so this can be streamlined by running"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "solution = sim.solve([0, 3600])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "when solving our simulation. Once we have the solution, we can define post-processed variable for the relevant variables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "t = solution[\"Time [s]\"]\n",
    "V = solution[\"Voltage [V]\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(for a list of all the available variables see [Tutorial 3](./tutorial-3-basic-plotting.ipynb)). These `ProcessedVariable` objects contain the datapoints for the corresponding variable, which can be accessed by calling the `entries` variable. For example, for voltage, we can call"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3.77048098, 3.75309871, 3.74569826, 3.74040906, 3.73582978,\n",
       "       3.73155017, 3.72743983, 3.72345507, 3.71958265, 3.71581858,\n",
       "       3.71216287, 3.70861698, 3.7051823 , 3.70185947, 3.69864846,\n",
       "       3.69554865, 3.69255894, 3.6896778 , 3.68690322, 3.68423281,\n",
       "       3.68166383, 3.67919326, 3.67681781, 3.67453394, 3.67233783,\n",
       "       3.6702254 , 3.66819225, 3.66623353, 3.66434383, 3.66251699,\n",
       "       3.66074577, 3.65902141, 3.65733311, 3.65566717, 3.65400602,\n",
       "       3.65232696, 3.6506007 , 3.64879012, 3.64684952, 3.64472566,\n",
       "       3.64236191, 3.63970731, 3.63673126, 3.63344172, 3.62989992,\n",
       "       3.62622171, 3.6225587 , 3.61906361, 3.61585516, 3.61299814,\n",
       "       3.61050386, 3.60834443, 3.606471  , 3.60482876, 3.60336628,\n",
       "       3.60203993, 3.60081505, 3.59966528, 3.59857137, 3.59751973,\n",
       "       3.59650118, 3.59550993, 3.59454272, 3.59359821, 3.59267644,\n",
       "       3.59177838, 3.59090556, 3.59005965, 3.58924208, 3.58845355,\n",
       "       3.58769359, 3.58695999, 3.58624826, 3.58555109, 3.58485777,\n",
       "       3.58415379, 3.5834204 , 3.58263444, 3.58176818, 3.58078926,\n",
       "       3.57966067, 3.57834049, 3.57678113, 3.57492782, 3.57271582,\n",
       "       3.57006555, 3.566875  , 3.56300793, 3.5582764 , 3.55241508,\n",
       "       3.54504405, 3.53561555, 3.52333845, 3.50707266, 3.48518447,\n",
       "       3.45535426, 3.41433385, 3.35766635, 3.27941791, 3.17203869])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "V.entries"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "which correspond to the data at the times"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([   0.        ,   36.36363636,   72.72727273,  109.09090909,\n",
       "        145.45454545,  181.81818182,  218.18181818,  254.54545455,\n",
       "        290.90909091,  327.27272727,  363.63636364,  400.        ,\n",
       "        436.36363636,  472.72727273,  509.09090909,  545.45454545,\n",
       "        581.81818182,  618.18181818,  654.54545455,  690.90909091,\n",
       "        727.27272727,  763.63636364,  800.        ,  836.36363636,\n",
       "        872.72727273,  909.09090909,  945.45454545,  981.81818182,\n",
       "       1018.18181818, 1054.54545455, 1090.90909091, 1127.27272727,\n",
       "       1163.63636364, 1200.        , 1236.36363636, 1272.72727273,\n",
       "       1309.09090909, 1345.45454545, 1381.81818182, 1418.18181818,\n",
       "       1454.54545455, 1490.90909091, 1527.27272727, 1563.63636364,\n",
       "       1600.        , 1636.36363636, 1672.72727273, 1709.09090909,\n",
       "       1745.45454545, 1781.81818182, 1818.18181818, 1854.54545455,\n",
       "       1890.90909091, 1927.27272727, 1963.63636364, 2000.        ,\n",
       "       2036.36363636, 2072.72727273, 2109.09090909, 2145.45454545,\n",
       "       2181.81818182, 2218.18181818, 2254.54545455, 2290.90909091,\n",
       "       2327.27272727, 2363.63636364, 2400.        , 2436.36363636,\n",
       "       2472.72727273, 2509.09090909, 2545.45454545, 2581.81818182,\n",
       "       2618.18181818, 2654.54545455, 2690.90909091, 2727.27272727,\n",
       "       2763.63636364, 2800.        , 2836.36363636, 2872.72727273,\n",
       "       2909.09090909, 2945.45454545, 2981.81818182, 3018.18181818,\n",
       "       3054.54545455, 3090.90909091, 3127.27272727, 3163.63636364,\n",
       "       3200.        , 3236.36363636, 3272.72727273, 3309.09090909,\n",
       "       3345.45454545, 3381.81818182, 3418.18181818, 3454.54545455,\n",
       "       3490.90909091, 3527.27272727, 3563.63636364, 3600.        ])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t.entries"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In addition, post-processed variables can be called at any time, which will return the interpolated value from the data above:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3.729495  , 3.70861698, 3.67812431, 3.65402263])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "V([200, 400, 780, 1236])  # times in seconds"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Saving the simulation and output data"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In some cases simulations might take a long time to run so it is advisable to save in your computer so it can be analysed later without re-running the simulation. You can save the whole simulation doing:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "sim.save(\"SPMe.pkl\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you now check the root directory of your notebooks you will notice that a new file called `\"SPMe.pkl\"` has appeared. We can load the stored simulation doing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "sim2 = pybamm.load(\"SPMe.pkl\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "which allows the same manipulation as the original simulation would allow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4c55af9203f344ca95df43e94633e8fc",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(FloatSlider(value=0.0, description='t', max=1.0, step=0.01), Output()), _dom_classes=('w…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<pybamm.plotting.quick_plot.QuickPlot at 0x7f5e5ac5c910>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sim2.plot()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively, we can just save the solution of the simulation in a similar way"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "sol = sim.solution\n",
    "sol.save(\"SPMe_sol.pkl\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and load it in a similar way too"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f98196a0055f45958cf6fa7b3d255e64",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(FloatSlider(value=0.0, description='t', max=1.0, step=0.01), Output()), _dom_classes=('w…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<pybamm.plotting.quick_plot.QuickPlot at 0x7f5e58ebb5d0>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sol2 = pybamm.load(\"SPMe_sol.pkl\")\n",
    "sol2.plot()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another option is to just save the data for some variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "sol.save_data(\"sol_data.pkl\", [\"Current [A]\", \"Voltage [V]\"])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or save it in `.csv` or `.mat` format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "sol.save_data(\"sol_data.csv\", [\"Current [A]\", \"Voltage [V]\"], to_format=\"csv\")\n",
    "# matlab needs names without spaces\n",
    "sol.save_data(\n",
    "    \"sol_data.mat\",\n",
    "    [\"Current [A]\", \"Voltage [V]\"],\n",
    "    to_format=\"matlab\",\n",
    "    short_names={\"Current [A]\": \"I\", \"Voltage [V]\": \"V\"},\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that while exporting `.pkl` works for all variables, exporting to `.csv` and `.mat` only works for 0D variables (i.e. variables the do not depend on space, only on time).\n",
    "\n",
    "In this notebook we have shown how to extract and store the outputs of PyBaMM's simulations. Next, in [Tutorial 7](./tutorial-7-model-options.ipynb) we will show how to change the model options."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before finishing we will remove the data files we saved so that we leave the directory as we found it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.remove(\"SPMe.pkl\")\n",
    "os.remove(\"SPMe_sol.pkl\")\n",
    "os.remove(\"sol_data.pkl\")\n",
    "os.remove(\"sol_data.csv\")\n",
    "os.remove(\"sol_data.mat\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "The relevant papers for this notebook are:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1] Joel A. E. Andersson, Joris Gillis, Greg Horn, James B. Rawlings, and Moritz Diehl. CasADi – A software framework for nonlinear optimization and optimal control. Mathematical Programming Computation, 11(1):1–36, 2019. doi:10.1007/s12532-018-0139-4.\n",
      "[2] Charles R. Harris, K. Jarrod Millman, Stéfan J. van der Walt, Ralf Gommers, Pauli Virtanen, David Cournapeau, Eric Wieser, Julian Taylor, Sebastian Berg, Nathaniel J. Smith, and others. Array programming with NumPy. Nature, 585(7825):357–362, 2020. doi:10.1038/s41586-020-2649-2.\n",
      "[3] Scott G. Marquis, Valentin Sulzer, Robert Timms, Colin P. Please, and S. Jon Chapman. An asymptotic derivation of a single particle model with electrolyte. Journal of The Electrochemical Society, 166(15):A3693–A3706, 2019. doi:10.1149/2.0341915jes.\n",
      "[4] Valentin Sulzer, Scott G. Marquis, Robert Timms, Martin Robinson, and S. Jon Chapman. Python Battery Mathematical Modelling (PyBaMM). Journal of Open Research Software, 9(1):14, 2021. doi:10.5334/jors.309.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "pybamm.print_citations()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9.13 ('python39-pybamm')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  },
  "vscode": {
   "interpreter": {
    "hash": "7dc94e087d5e42ea54b14035c48a0a59093d5180e7f512a1db8f70eb4b99d01e"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
